// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <deque>

#include "base/big_endian.h"
#include "base/macros.h"
#include "base/test/simple_test_tick_clock.h"
#include "media/base/fake_single_thread_task_runner.h"
#include "media/cast/net/pacing/paced_sender.h"
#include "testing/gmock/include/gmock/gmock.h"

using testing::_;

namespace media {
namespace cast {
    namespace {

        const uint8_t kValue = 123;
        const size_t kSize1 = 101;
        const size_t kSize2 = 102;
        const size_t kSize3 = 103;
        const size_t kSize4 = 104;
        const size_t kNackSize = 105;
        const int64_t kStartMillisecond = INT64_C(12345678900000);
        const uint32_t kVideoSsrc = 0x1234;
        const uint32_t kAudioSsrc = 0x5678;
        const uint32_t kVideoFrameRtpTimestamp = 12345;
        const uint32_t kAudioFrameRtpTimestamp = 23456;

        // RTCP packets don't really have a packet ID.  However, the bytes where
        // TestPacketSender checks for the ID should be set to 31611, so we'll just
        // check that.
        const uint16_t kRtcpPacketIdMagic = UINT16_C(31611);

        class TestPacketSender : public PacketTransport {
        public:
            TestPacketSender()
                : bytes_sent_(0)
            {
            }

            bool SendPacket(PacketRef packet, const base::Closure& cb) final
            {
                EXPECT_FALSE(expected_packet_sizes_.empty());
                size_t expected_packet_size = expected_packet_sizes_.front();
                expected_packet_sizes_.pop_front();
                EXPECT_EQ(expected_packet_size, packet->data.size());
                bytes_sent_ += packet->data.size();

                // Parse for the packet ID and confirm it is the next one we expect.
                EXPECT_LE(kSize1, packet->data.size());
                base::BigEndianReader reader(reinterpret_cast<char*>(&packet->data[0]),
                    packet->data.size());
                bool success = reader.Skip(14);
                uint16_t packet_id = 0xffff;
                success &= reader.ReadU16(&packet_id);
                EXPECT_TRUE(success);
                const uint16_t expected_packet_id = expected_packet_ids_.front();
                expected_packet_ids_.pop_front();
                EXPECT_EQ(expected_packet_id, packet_id);

                return true;
            }

            int64_t GetBytesSent() final { return bytes_sent_; }

            void StartReceiving(
                const PacketReceiverCallbackWithStatus& packet_receiver) final { }

            void StopReceiving() final { }

            void AddExpectedSizesAndPacketIds(int packet_size,
                uint16_t first_packet_id,
                int sequence_length)
            {
                for (int i = 0; i < sequence_length; ++i) {
                    expected_packet_sizes_.push_back(packet_size);
                    expected_packet_ids_.push_back(first_packet_id++);
                }
            }

            bool expecting_nothing_else() const { return expected_packet_sizes_.empty(); }

        private:
            std::deque<int> expected_packet_sizes_;
            std::deque<uint16_t> expected_packet_ids_;
            int64_t bytes_sent_;

            DISALLOW_COPY_AND_ASSIGN(TestPacketSender);
        };

        class PacedSenderTest : public ::testing::Test {
        protected:
            PacedSenderTest()
            {
                testing_clock_.Advance(
                    base::TimeDelta::FromMilliseconds(kStartMillisecond));
                task_runner_ = new FakeSingleThreadTaskRunner(&testing_clock_);
                paced_sender_.reset(new PacedSender(kTargetBurstSize, kMaxBurstSize,
                    &testing_clock_, &packet_events_,
                    &mock_transport_, task_runner_));
                paced_sender_->RegisterSsrc(kAudioSsrc, true);
                paced_sender_->RegisterSsrc(kVideoSsrc, false);
            }

            static void UpdateCastTransportStatus(CastTransportStatus status)
            {
                NOTREACHED();
            }

            SendPacketVector CreateSendPacketVector(size_t packet_size,
                int num_of_packets_in_frame,
                bool audio)
            {
                DCHECK_GE(packet_size, 12u);
                SendPacketVector packets;
                base::TimeTicks frame_tick = testing_clock_.NowTicks();
                // Advance the clock so that we don't get the same |frame_tick|
                // next time this function is called.
                testing_clock_.Advance(base::TimeDelta::FromMilliseconds(1));
                for (int i = 0; i < num_of_packets_in_frame; ++i) {
                    PacketKey key(frame_tick, audio ? kAudioSsrc : kVideoSsrc,
                        FrameId::first(), i);

                    PacketRef packet(new base::RefCountedData<Packet>);
                    packet->data.resize(packet_size, kValue);
                    // Fill-in packet header fields to test the header parsing (for populating
                    // the logging events).
                    base::BigEndianWriter writer(reinterpret_cast<char*>(&packet->data[0]),
                        packet_size);
                    bool success = writer.Skip(4);
                    success &= writer.WriteU32(audio ? kAudioFrameRtpTimestamp
                                                     : kVideoFrameRtpTimestamp);
                    success &= writer.WriteU32(audio ? kAudioSsrc : kVideoSsrc);
                    success &= writer.Skip(2);
                    success &= writer.WriteU16(i);
                    success &= writer.WriteU16(num_of_packets_in_frame - 1);
                    CHECK(success);
                    packets.push_back(std::make_pair(key, packet));
                }
                return packets;
            }

            void SendWithoutBursting(const SendPacketVector& packets)
            {
                const size_t kBatchSize = 10;
                for (size_t i = 0; i < packets.size(); i += kBatchSize) {
                    const SendPacketVector next_batch(
                        packets.begin() + i,
                        packets.begin() + i + std::min(packets.size() - i, kBatchSize));
                    ASSERT_TRUE(paced_sender_->SendPackets(next_batch));
                    testing_clock_.Advance(base::TimeDelta::FromMilliseconds(10));
                    task_runner_->RunTasks();
                }
            }

            // Use this function to drain the packet list in PacedSender without having
            // to test the pacing implementation details.
            bool RunUntilEmpty(int max_tries)
            {
                for (int i = 0; i < max_tries; i++) {
                    testing_clock_.Advance(base::TimeDelta::FromMilliseconds(10));
                    task_runner_->RunTasks();
                    if (mock_transport_.expecting_nothing_else())
                        return true;
                }

                return mock_transport_.expecting_nothing_else();
            }

            std::vector<PacketEvent> packet_events_;
            base::SimpleTestTickClock testing_clock_;
            TestPacketSender mock_transport_;
            scoped_refptr<FakeSingleThreadTaskRunner> task_runner_;
            std::unique_ptr<PacedSender> paced_sender_;

            DISALLOW_COPY_AND_ASSIGN(PacedSenderTest);
        };

    } // namespace

    TEST_F(PacedSenderTest, PassThroughRtcp)
    {
        SendPacketVector packets = CreateSendPacketVector(kSize1, 1, true);

        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(0), 1);
        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(0), 1);
        EXPECT_TRUE(paced_sender_->SendPackets(packets));
        EXPECT_TRUE(paced_sender_->ResendPackets(packets, DedupInfo()));

        mock_transport_.AddExpectedSizesAndPacketIds(kSize2, kRtcpPacketIdMagic, 1);
        Packet tmp(kSize2, kValue);
        EXPECT_TRUE(paced_sender_->SendRtcpPacket(
            1,
            new base::RefCountedData<Packet>(tmp)));
    }

    TEST_F(PacedSenderTest, BasicPace)
    {
        int num_of_packets = 27;
        SendPacketVector packets = CreateSendPacketVector(kSize1,
            num_of_packets,
            false);
        const base::TimeTicks earliest_event_timestamp = testing_clock_.NowTicks();

        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(0), 10);
        EXPECT_TRUE(paced_sender_->SendPackets(packets));

        // Check that we get the next burst.
        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(10), 10);

        base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(10);
        testing_clock_.Advance(timeout);
        task_runner_->RunTasks();

        // If we call process too early make sure we don't send any packets.
        timeout = base::TimeDelta::FromMilliseconds(5);
        testing_clock_.Advance(timeout);
        task_runner_->RunTasks();

        // Check that we get the next burst.
        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(20), 7);
        testing_clock_.Advance(timeout);
        task_runner_->RunTasks();

        // Check that we don't get any more packets.
        EXPECT_TRUE(RunUntilEmpty(3));
        const base::TimeTicks latest_event_timestamp = testing_clock_.NowTicks();

        // Check that packet logging events match expected values.
        EXPECT_EQ(num_of_packets, static_cast<int>(packet_events_.size()));
        uint16_t expected_packet_id = 0;
        for (const PacketEvent& e : packet_events_) {
            ASSERT_LE(earliest_event_timestamp, e.timestamp);
            ASSERT_GE(latest_event_timestamp, e.timestamp);
            ASSERT_EQ(PACKET_SENT_TO_NETWORK, e.type);
            ASSERT_EQ(VIDEO_EVENT, e.media_type);
            ASSERT_EQ(kVideoFrameRtpTimestamp, e.rtp_timestamp.lower_32_bits());
            ASSERT_EQ(num_of_packets - 1, e.max_packet_id);
            ASSERT_EQ(expected_packet_id++, e.packet_id);
            ASSERT_EQ(kSize1, e.size);
        }
    }

    TEST_F(PacedSenderTest, PaceWithNack)
    {
        // Testing what happen when we get multiple NACK requests for a fully lost
        // frames just as we sent the first packets in a frame.
        int num_of_packets_in_frame = 12;
        int num_of_packets_in_nack = 12;

        SendPacketVector nack_packets = CreateSendPacketVector(kNackSize, num_of_packets_in_nack, false);

        SendPacketVector first_frame_packets = CreateSendPacketVector(kSize1, num_of_packets_in_frame, false);

        SendPacketVector second_frame_packets = CreateSendPacketVector(kSize2, num_of_packets_in_frame, true);

        // Check that the first burst of the frame go out on the wire.
        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(0), 10);
        EXPECT_TRUE(paced_sender_->SendPackets(first_frame_packets));

        // Add first NACK request.
        EXPECT_TRUE(paced_sender_->ResendPackets(nack_packets, DedupInfo()));

        // Check that we get the first NACK burst.
        mock_transport_.AddExpectedSizesAndPacketIds(kNackSize, UINT16_C(0), 10);
        base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(10);
        testing_clock_.Advance(timeout);
        task_runner_->RunTasks();

        // Add second NACK request.
        EXPECT_TRUE(paced_sender_->ResendPackets(nack_packets, DedupInfo()));

        // Check that we get the next NACK burst.
        mock_transport_.AddExpectedSizesAndPacketIds(kNackSize, UINT16_C(10), 2);
        mock_transport_.AddExpectedSizesAndPacketIds(kNackSize, UINT16_C(0), 8);
        testing_clock_.Advance(timeout);
        task_runner_->RunTasks();

        // End of NACK plus two packets from the oldest frame.
        // Note that two of the NACKs have been de-duped.
        mock_transport_.AddExpectedSizesAndPacketIds(kNackSize, UINT16_C(8), 2);
        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(10), 2);
        testing_clock_.Advance(timeout);
        task_runner_->RunTasks();

        // Add second frame.
        // Make sure we don't delay the second frame due to the previous packets.
        mock_transport_.AddExpectedSizesAndPacketIds(kSize2, UINT16_C(0), 10);
        EXPECT_TRUE(paced_sender_->SendPackets(second_frame_packets));

        // Last packets of frame 2.
        mock_transport_.AddExpectedSizesAndPacketIds(kSize2, UINT16_C(10), 2);
        testing_clock_.Advance(timeout);
        task_runner_->RunTasks();

        // No more packets.
        EXPECT_TRUE(RunUntilEmpty(5));

        int expected_video_network_event_count = num_of_packets_in_frame;
        int expected_video_retransmitted_event_count = 2 * num_of_packets_in_nack;
        expected_video_retransmitted_event_count -= 2; // 2 packets deduped
        int expected_audio_network_event_count = num_of_packets_in_frame;
        EXPECT_EQ(expected_video_network_event_count + expected_video_retransmitted_event_count + expected_audio_network_event_count,
            static_cast<int>(packet_events_.size()));
        int audio_network_event_count = 0;
        int video_network_event_count = 0;
        int video_retransmitted_event_count = 0;
        for (const PacketEvent& e : packet_events_) {
            if (e.type == PACKET_SENT_TO_NETWORK) {
                if (e.media_type == VIDEO_EVENT)
                    video_network_event_count++;
                else
                    audio_network_event_count++;
            } else if (e.type == PACKET_RETRANSMITTED) {
                if (e.media_type == VIDEO_EVENT)
                    video_retransmitted_event_count++;
            } else {
                FAIL() << "Got unexpected event type " << CastLoggingToString(e.type);
            }
        }
        EXPECT_EQ(expected_audio_network_event_count, audio_network_event_count);
        EXPECT_EQ(expected_video_network_event_count, video_network_event_count);
        EXPECT_EQ(expected_video_retransmitted_event_count,
            video_retransmitted_event_count);
    }

    TEST_F(PacedSenderTest, PaceWith60fps)
    {
        // Testing what happen when we get multiple NACK requests for a fully lost
        // frames just as we sent the first packets in a frame.
        int num_of_packets_in_frame = 17;

        SendPacketVector first_frame_packets = CreateSendPacketVector(kSize1, num_of_packets_in_frame, false);

        SendPacketVector second_frame_packets = CreateSendPacketVector(kSize2, num_of_packets_in_frame, false);

        SendPacketVector third_frame_packets = CreateSendPacketVector(kSize3, num_of_packets_in_frame, false);

        SendPacketVector fourth_frame_packets = CreateSendPacketVector(kSize4, num_of_packets_in_frame, false);

        base::TimeDelta timeout_10ms = base::TimeDelta::FromMilliseconds(10);

        // Check that the first burst of the frame go out on the wire.
        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(0), 10);
        EXPECT_TRUE(paced_sender_->SendPackets(first_frame_packets));

        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(10), 7);
        testing_clock_.Advance(timeout_10ms);
        task_runner_->RunTasks();

        testing_clock_.Advance(base::TimeDelta::FromMilliseconds(6));

        // Add second frame, after 16 ms.
        mock_transport_.AddExpectedSizesAndPacketIds(kSize2, UINT16_C(0), 3);
        EXPECT_TRUE(paced_sender_->SendPackets(second_frame_packets));
        testing_clock_.Advance(base::TimeDelta::FromMilliseconds(4));

        mock_transport_.AddExpectedSizesAndPacketIds(kSize2, UINT16_C(3), 10);
        testing_clock_.Advance(timeout_10ms);
        task_runner_->RunTasks();

        mock_transport_.AddExpectedSizesAndPacketIds(kSize2, UINT16_C(13), 4);
        testing_clock_.Advance(timeout_10ms);
        task_runner_->RunTasks();

        testing_clock_.Advance(base::TimeDelta::FromMilliseconds(3));

        // Add third frame, after 33 ms.
        mock_transport_.AddExpectedSizesAndPacketIds(kSize3, UINT16_C(0), 6);
        EXPECT_TRUE(paced_sender_->SendPackets(third_frame_packets));

        mock_transport_.AddExpectedSizesAndPacketIds(kSize3, UINT16_C(6), 10);
        testing_clock_.Advance(base::TimeDelta::FromMilliseconds(7));
        task_runner_->RunTasks();

        // Add fourth frame, after 50 ms.
        EXPECT_TRUE(paced_sender_->SendPackets(fourth_frame_packets));

        mock_transport_.AddExpectedSizesAndPacketIds(kSize3, UINT16_C(16), 1);
        mock_transport_.AddExpectedSizesAndPacketIds(kSize4, UINT16_C(0), 9);
        testing_clock_.Advance(timeout_10ms);
        task_runner_->RunTasks();

        mock_transport_.AddExpectedSizesAndPacketIds(kSize4, UINT16_C(9), 8);
        testing_clock_.Advance(timeout_10ms);
        task_runner_->RunTasks();

        testing_clock_.Advance(timeout_10ms);
        task_runner_->RunTasks();

        testing_clock_.Advance(timeout_10ms);
        task_runner_->RunTasks();

        // No more packets.
        EXPECT_TRUE(RunUntilEmpty(5));
    }

    TEST_F(PacedSenderTest, SendPriority)
    {
        // Actual order to the network is:
        // 1. Video packets x 10.
        // 2. RTCP packet x 1.
        // 3. Audio packet x 1.
        // 4. Video retransmission packet x 10.
        // 5. Video packet x 10.
        mock_transport_.AddExpectedSizesAndPacketIds(kSize2, UINT16_C(0), 10);
        mock_transport_.AddExpectedSizesAndPacketIds(kSize3, kRtcpPacketIdMagic, 1);
        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(0), 1);
        mock_transport_.AddExpectedSizesAndPacketIds(kSize4, UINT16_C(0), 10);
        mock_transport_.AddExpectedSizesAndPacketIds(kSize2, UINT16_C(10), 10);

        paced_sender_->RegisterPrioritySsrc(kAudioSsrc);

        // Retransmission packets with the earlier timestamp.
        SendPacketVector resend_packets = CreateSendPacketVector(kSize4, 10, false);
        testing_clock_.Advance(base::TimeDelta::FromMilliseconds(10));

        // Send 20 normal video packets. Only 10 will be sent in this
        // call, the rest will be sitting in the queue waiting for pacing.
        EXPECT_TRUE(paced_sender_->SendPackets(
            CreateSendPacketVector(kSize2, 20, false)));

        testing_clock_.Advance(base::TimeDelta::FromMilliseconds(10));

        // Send normal audio packet. This is queued and will be sent
        // earlier than video packets.
        EXPECT_TRUE(paced_sender_->SendPackets(
            CreateSendPacketVector(kSize1, 1, true)));

        // Send RTCP packet. This is queued and will be sent first.
        EXPECT_TRUE(paced_sender_->SendRtcpPacket(
            kVideoSsrc,
            new base::RefCountedData<Packet>(Packet(kSize3, kValue))));

        // Resend video packets. This is queued and will be sent
        // earlier than normal video packets.
        EXPECT_TRUE(paced_sender_->ResendPackets(resend_packets, DedupInfo()));

        // Roll the clock. Queued packets will be sent in this order:
        // 1. RTCP packet x 1.
        // 2. Audio packet x 1.
        // 3. Video retransmission packet x 10.
        // 4. Video packet x 10.
        task_runner_->RunTasks();
        EXPECT_TRUE(RunUntilEmpty(4));
    }

    TEST_F(PacedSenderTest, GetLastByteSent)
    {
        SendPacketVector packets1 = CreateSendPacketVector(kSize1, 1, true);
        SendPacketVector packets2 = CreateSendPacketVector(kSize1, 1, false);

        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(0), 1);
        EXPECT_TRUE(paced_sender_->SendPackets(packets1));
        EXPECT_EQ(static_cast<int64_t>(kSize1),
            paced_sender_->GetLastByteSentForPacket(packets1[0].first));
        EXPECT_EQ(static_cast<int64_t>(kSize1),
            paced_sender_->GetLastByteSentForSsrc(kAudioSsrc));
        EXPECT_EQ(0, paced_sender_->GetLastByteSentForSsrc(kVideoSsrc));

        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(0), 1);
        EXPECT_TRUE(paced_sender_->SendPackets(packets2));
        EXPECT_EQ(static_cast<int64_t>(2 * kSize1),
            paced_sender_->GetLastByteSentForPacket(packets2[0].first));
        EXPECT_EQ(static_cast<int64_t>(kSize1),
            paced_sender_->GetLastByteSentForSsrc(kAudioSsrc));
        EXPECT_EQ(static_cast<int64_t>(2 * kSize1),
            paced_sender_->GetLastByteSentForSsrc(kVideoSsrc));

        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(0), 1);
        EXPECT_TRUE(paced_sender_->ResendPackets(packets1, DedupInfo()));
        EXPECT_EQ(static_cast<int64_t>(3 * kSize1),
            paced_sender_->GetLastByteSentForPacket(packets1[0].first));
        EXPECT_EQ(static_cast<int64_t>(3 * kSize1),
            paced_sender_->GetLastByteSentForSsrc(kAudioSsrc));
        EXPECT_EQ(static_cast<int64_t>(2 * kSize1),
            paced_sender_->GetLastByteSentForSsrc(kVideoSsrc));

        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(0), 1);
        EXPECT_TRUE(paced_sender_->ResendPackets(packets2, DedupInfo()));
        EXPECT_EQ(static_cast<int64_t>(4 * kSize1),
            paced_sender_->GetLastByteSentForPacket(packets2[0].first));
        EXPECT_EQ(static_cast<int64_t>(3 * kSize1),
            paced_sender_->GetLastByteSentForSsrc(kAudioSsrc));
        EXPECT_EQ(static_cast<int64_t>(4 * kSize1),
            paced_sender_->GetLastByteSentForSsrc(kVideoSsrc));
    }

    TEST_F(PacedSenderTest, DedupWithResendInterval)
    {
        SendPacketVector packets = CreateSendPacketVector(kSize1, 1, true);
        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(0), 1);
        EXPECT_TRUE(paced_sender_->SendPackets(packets));
        testing_clock_.Advance(base::TimeDelta::FromMilliseconds(10));

        DedupInfo dedup_info;
        dedup_info.resend_interval = base::TimeDelta::FromMilliseconds(20);

        // This packet will not be sent.
        EXPECT_TRUE(paced_sender_->ResendPackets(packets, dedup_info));
        EXPECT_EQ(static_cast<int64_t>(kSize1), mock_transport_.GetBytesSent());

        dedup_info.resend_interval = base::TimeDelta::FromMilliseconds(5);
        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(0), 1);
        EXPECT_TRUE(paced_sender_->ResendPackets(packets, dedup_info));
        EXPECT_EQ(static_cast<int64_t>(2 * kSize1), mock_transport_.GetBytesSent());
    }

    TEST_F(PacedSenderTest, AllPacketsInSameFrameAreResentFairly)
    {
        const int kNumPackets = 400;
        SendPacketVector packets = CreateSendPacketVector(kSize1, kNumPackets, false);

        // Send a large frame (400 packets, yeah!).  Confirm that the paced sender
        // sends each packet in the frame exactly once.
        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(0),
            kNumPackets);
        SendWithoutBursting(packets);
        ASSERT_TRUE(mock_transport_.expecting_nothing_else());

        // Resend packets 2 and 3.  Confirm that the paced sender sends them.  Then,
        // resend all of the first 10 packets.  The paced sender should send packets
        // 0, 1, and 4 through 9 first, and then 2 and 3.
        SendPacketVector couple_of_packets;
        couple_of_packets.push_back(packets[2]);
        couple_of_packets.push_back(packets[3]);

        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(2), 2);
        SendWithoutBursting(couple_of_packets);
        ASSERT_TRUE(mock_transport_.expecting_nothing_else());

        SendPacketVector first_ten_packets;
        for (size_t i = 0; i < 10; ++i)
            first_ten_packets.push_back(packets[i]);
        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(0), 2);
        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(4), 6);
        mock_transport_.AddExpectedSizesAndPacketIds(kSize1, UINT16_C(2), 2);
        SendWithoutBursting(first_ten_packets);
        ASSERT_TRUE(mock_transport_.expecting_nothing_else());
    }

} // namespace cast
} // namespace media
